import tkinter as tk
from tkinter import ttk, messagebox
import webbrowser
from datetime import datetime
from typing import List

from config_loader import get_full_config_path
from core.spider.pure_api_zero import ApiZeroSeven
from core.util.bifen_data_parser import FootballMatchParser
from db.entity2 import MatchDataV2
from gui.components.components import PlaceholderEntry
from gui.notification_config_gui import NotificationConfigFrame
from gui.odds_monitor import OddsMonitor
from core.util.bf_data_parser import BfDataParser
from core.util.web007util import Spider007Util
from notify.audio_sender import AudioSender
from notify.email_sender import EmailSender
import os
from db.entity2 import get_base_dir


class MatchViewer:
    def __init__(self, root):
        self.root = root
        # 只有当root是Tk窗口时才设置标题和几何尺寸
        if hasattr(self.root, 'title'):
            self.root.title("007数据监测")
        if hasattr(self.root, 'geometry'):
            self.root.geometry("1000x700")

        # 初始化为空数据，防止启动时因网络问题卡死
        self.match_data: List[MatchDataV2] = []
        self.all_match_data = []

        self.selected_items = set()
        self.log_messages = [
            "系统启动成功，请点击'刷新'按钮加载数据"
        ]

        # 初始化日志相关属性
        self.log_text = None
        self.log_paused = False
        self.log_running = True

        # 初始化盘口监控系统
        self.odds_monitor = OddsMonitor(self)

        self.setup_ui()
        # 启动盘口监控状态更新
        self.update_monitor_status()
        
        # 默认启动监控
        self.odds_monitor.start_monitoring()
        
        # 应用默认筛选
        self.filter_matches()

        # UI加载完成后自动刷新数据（延迟执行，避免阻塞启动）
        self.root.after(200, self.refresh_data)

    def setup_ui(self):
        # 主容器 - 使用PanedWindow实现可调整的分割
        main_paned = ttk.PanedWindow(self.root, orient=tk.VERTICAL)
        main_paned.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 上半部分：比赛信息区域
        top_frame = ttk.Frame(main_paned)
        main_paned.add(top_frame, weight=3)  # 权重较大，初始占用更多空间

        # 下半部分：日志区域
        bottom_frame = ttk.Frame(main_paned)
        main_paned.add(bottom_frame, weight=1)  # 权重较小

        self.setup_match_ui(top_frame)
        self.setup_log_ui(bottom_frame)

    def setup_match_ui(self, parent):
        # 创建筛选框架
        filter_frame = tk.Frame(parent)
        filter_frame.pack(fill=tk.X, padx=10, pady=5)

        # 状态筛选标签
        status_label = tk.Label(filter_frame, text="状态筛选:", font=("Arial", 10))
        status_label.pack(side=tk.LEFT, padx=(0, 5))

        # 状态筛选下拉框
        self.status_filter_var = tk.StringVar(value="滚球中")
        self.status_combobox = ttk.Combobox(
            filter_frame,
            textvariable=self.status_filter_var,
            values=["全部", "滚球中", "未开赛", "已完场"],
            state="readonly",
            width=8,
            font=("Arial", 10)
        )
        self.status_combobox.pack(side=tk.LEFT, padx=(0, 15))
        self.status_combobox.bind("<<ComboboxSelected>>", self.filter_matches)

        # 筛选标签
        filter_label = tk.Label(filter_frame, text="球队筛选:", font=("Arial", 10))
        filter_label.pack(side=tk.LEFT, padx=(0, 5))

        # 使用封装的PlaceholderEntry组件
        self.filter_entry = PlaceholderEntry(
            filter_frame,
            placeholder_text="输入球队名称进行筛选",
            placeholder_color="grey",
            normal_color="black",
            width=30,
            font=("Arial", 10)
        )
        self.filter_entry.pack(side=tk.LEFT, padx=5)

        # 绑定筛选事件
        self.filter_entry.bind("<KeyRelease>", self.filter_matches)

        # 清除筛选按钮
        clear_filter_btn = tk.Button(filter_frame, text="清除筛选",
                                     command=self.clear_filter,
                                     bg="#9E9E9E", fg="white", font=("Arial", 9))
        clear_filter_btn.pack(side=tk.LEFT, padx=5)

        # 筛选结果提示
        self.filter_info = tk.Label(filter_frame, text="",
                                    font=("Arial", 9), fg="#666")
        self.filter_info.pack(side=tk.LEFT, padx=10)

        # 创建工具栏框架
        toolbar = tk.Frame(parent)
        toolbar.pack(fill=tk.X, padx=10, pady=5)

        # 全选按钮
        select_all_btn = tk.Button(toolbar, text="全选", command=self.select_all,
                                   bg="#4CAF50", fg="white", font=("Arial", 10))
        select_all_btn.pack(side=tk.LEFT, padx=5)

        # 反选按钮
        invert_select_btn = tk.Button(toolbar, text="反选", command=self.invert_selection,
                                      bg="#2196F3", fg="white", font=("Arial", 10))
        invert_select_btn.pack(side=tk.LEFT, padx=5)

        # # 删除按钮
        # delete_btn = tk.Button(toolbar, text="删除选中", command=self.delete_selected,
        #                        bg="#f44336", fg="white", font=("Arial", 10, "bold"))
        # delete_btn.pack(side=tk.LEFT, padx=5)

        # 刷新按钮
        refresh_btn = tk.Button(toolbar, text="刷新", command=self.refresh_data,
                                bg="#FF9800", fg="white", font=("Arial", 10))
        refresh_btn.pack(side=tk.LEFT, padx=5)

        # 盘口监控按钮
        monitor_btn = tk.Button(toolbar, text="盘口监控", command=self.show_monitor_dialog,
                                bg="#607D8B", fg="white", font=("Arial", 10))
        monitor_btn.pack(side=tk.LEFT, padx=5)

        # 批量监控按钮
        batch_monitor_btn = tk.Button(toolbar, text="批量监控", command=self.add_batch_monitoring,
                                      bg="#4CAF50", fg="white", font=("Arial", 10))
        batch_monitor_btn.pack(side=tk.LEFT, padx=5)

        # 清空监控按钮
        clear_monitor_btn = tk.Button(toolbar, text="清空监控", command=self.clear_all_monitoring,
                                      bg="#FF5722", fg="white", font=("Arial", 10))
        clear_monitor_btn.pack(side=tk.LEFT, padx=5)

        # 创建表格框架
        table_frame = tk.Frame(parent)
        table_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 创建Treeview控件
        self.create_table(table_frame)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set(f"总共 {len(self.match_data)} 场比赛")
        status_bar = tk.Label(parent, textvariable=self.status_var,
                              relief=tk.SUNKEN, anchor=tk.W, font=("Arial", 9))
        status_bar.pack(fill=tk.X, side=tk.BOTTOM)

        # 创建右键菜单
        self.create_context_menu()

    def setup_log_ui(self, parent):
        """设置日志界面"""
        # 日志区域标题
        log_title = tk.Label(parent, text="软件运行日志",
                             font=("Arial", 12, "bold"), fg="#333")
        log_title.pack(anchor=tk.W, padx=10, pady=(5, 0))

        # 日志工具栏
        log_toolbar = tk.Frame(parent)
        log_toolbar.pack(fill=tk.X, padx=10, pady=5)

        # 日志控制按钮
        clear_log_btn = tk.Button(log_toolbar, text="清空日志",
                                  command=self.clear_logs,
                                  bg="#607D8B", fg="white", font=("Arial", 9))
        clear_log_btn.pack(side=tk.LEFT, padx=5)

        pause_log_btn = tk.Button(log_toolbar, text="暂停/继续",
                                  command=self.toggle_log_pause,
                                  bg="#795548", fg="white", font=("Arial", 9))
        pause_log_btn.pack(side=tk.LEFT, padx=5)

        # 日志级别筛选
        log_level_label = tk.Label(log_toolbar, text="日志级别:", font=("Arial", 9))
        log_level_label.pack(side=tk.LEFT, padx=(20, 5))

        self.log_level_var = tk.StringVar(value="ALL")
        log_levels = [("全部", "ALL"), ("信息", "INFO"), ("警告", "WARN"), ("错误", "ERROR")]
        for text, level in log_levels:
            rb = tk.Radiobutton(log_toolbar, text=text, variable=self.log_level_var,
                                value=level, command=self.filter_logs, font=("Arial", 8))
            rb.pack(side=tk.LEFT, padx=2)

        # 自动滚动复选框
        self.auto_scroll_var = tk.BooleanVar(value=True)
        auto_scroll_cb = tk.Checkbutton(log_toolbar, text="自动滚动",
                                        variable=self.auto_scroll_var, font=("Arial", 9))
        auto_scroll_cb.pack(side=tk.RIGHT, padx=5)

        # 创建滚动文本框用于显示日志
        log_frame = tk.Frame(parent)
        log_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        # 创建垂直滚动条
        v_scrollbar = ttk.Scrollbar(log_frame)
        v_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 创建水平滚动条
        h_scrollbar = ttk.Scrollbar(log_frame, orient=tk.HORIZONTAL)
        h_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)

        # 创建日志文本框
        self.log_text = tk.Text(log_frame,
                                width=80,  # 调整日志框宽度
                                height=10,
                                yscrollcommand=v_scrollbar.set,
                                xscrollcommand=h_scrollbar.set,
                                wrap=tk.NONE,  # 不自动换行，使用水平滚动条
                                font=("Consolas", 9),
                                bg="#1E1E1E",  # 深色背景
                                fg="#FFFFFF",  # 白色文字
                                selectbackground="#264F78",  # 选中背景色
                                insertbackground="white")  # 光标颜色

        self.log_text.pack(fill=tk.BOTH, expand=True)

        # 配置滚动条
        v_scrollbar.config(command=self.log_text.yview)
        h_scrollbar.config(command=self.log_text.xview)

        # 配置标签样式（不同日志级别不同颜色）
        self.log_text.tag_configure("INFO", foreground="#4CAF50")  # 绿色
        self.log_text.tag_configure("WARN", foreground="#FF9800")  # 橙色
        self.log_text.tag_configure("ERROR", foreground="#F44336")  # 红色
        self.log_text.tag_configure("DEBUG", foreground="#2196F3")  # 蓝色
        self.log_text.tag_configure("TIME", foreground="#9E9E9E")  # 灰色时间戳

        # 初始化日志显示
        self.update_log_display()

        # 日志状态
        self.log_lines = 0

    def create_table(self, parent):
        # 创建滚动条
        scrollbar_y = ttk.Scrollbar(parent, orient=tk.VERTICAL)
        scrollbar_x = ttk.Scrollbar(parent, orient=tk.HORIZONTAL)

        # 创建Treeview
        columns = ("选择", "id", "时间", "赛事", "状态", "比赛球队", "比分", "半场", "监控状态")
        self.tree = ttk.Treeview(parent, columns=columns, show="tree headings",
                                 yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set,
                                 selectmode="extended")

        # 配置列
        self.tree.column("#0", width=0, stretch=tk.NO)
        self.tree.column("选择", width=60, anchor=tk.CENTER)
        self.tree.column("id", width=60, anchor=tk.CENTER)
        self.tree.column("时间", width=120, anchor=tk.CENTER)

        self.tree.column("赛事", width=80, anchor=tk.CENTER)
        self.tree.column("状态", width=80, anchor=tk.CENTER)
        self.tree.column("比赛球队", width=200, anchor=tk.CENTER)
        self.tree.column("比分", width=80, anchor=tk.CENTER)
        self.tree.column("半场", width=80, anchor=tk.CENTER)
        self.tree.column("赛事", width=100, anchor=tk.CENTER)
        self.tree.column("监控状态", width=80, anchor=tk.CENTER)

        # 配置表头
        for col in columns:
            self.tree.heading(col, text=col)

        # 添加数据
        self.populate_data()

        # 绑定事件
        self.tree.bind("<Button-1>", self.on_click)
        self.tree.bind("<Delete>", self.delete_selected)

        # 绑定右键点击事件
        self.tree.bind("<Button-3>", self.show_context_menu)

        # 配置标签样式（高亮）
        self.tree.tag_configure("alert_highlight", background="yellow", foreground="black")

        # 布局
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)
        scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

        # 配置滚动条
        scrollbar_y.config(command=self.tree.yview)
        scrollbar_x.config(command=self.tree.xview)

    def create_context_menu(self):
        """创建右键菜单"""
        self.context_menu = tk.Menu(self.root, tearoff=0)
        self.context_menu.add_command(label="添加监控", command=self.add_monitoring)
        # self.context_menu.add_command(label="删除监控", command=self.remove_monitoring)
        self.context_menu.add_separator()
        self.context_menu.add_command(label="跳转到源网页", command=self.open_source_page)

        # 绑定菜单隐藏事件
        self.tree.bind("<Button-1>", self.hide_context_menu)

    def show_context_menu(self, event):
        """显示右键菜单"""
        # 获取点击的行
        item = self.tree.identify_row(event.y)
        if item:
            # 选中该行
            self.tree.selection_set(item)

            # 获取行的数据
            values = self.tree.item(item, 'values')
            if values:
                # 获取监控状态
                monitoring_status = values[8] if len(values) > 8 else "未监控"

                # 根据监控状态更新菜单项
                self.context_menu.entryconfig(0, label="添加监控" if monitoring_status == "未监控" else "取消监控")
                self.context_menu.entryconfig(1, state=tk.NORMAL if monitoring_status == "监控中" else tk.DISABLED)

            # 显示菜单
            self.context_menu.post(event.x_root, event.y_root)

    def hide_context_menu(self, event):
        """隐藏右键菜单"""
        if self.context_menu:
            self.context_menu.unpost()

    def add_monitoring(self):
        """添加监控"""
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showwarning("警告", "请先选择要监控的比赛")
            return

        for item in selected_items:
            values = list(self.tree.item(item, 'values'))
            if len(values) > 8:
                # 更新监控状态
                values[8] = "监控中"
                self.tree.item(item, values=values)

                # 更新数据
                item_index = int(item)
                if item_index < len(self.match_data):
                    self.match_data[item_index].是否热门 = True
                    match_id = self.match_data[item_index].比赛ID
                    self.odds_monitor.add_monitored_match(match_id)

                # 记录日志
                match_name = values[5]  # 比赛球队
                self.add_log(f"已添加监控: {match_name}", "INFO")

        messagebox.showinfo("成功", "监控添加成功！")

    def remove_monitoring(self):
        """删除监控"""
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showwarning("警告", "请先选择要取消监控的比赛")
            return

        for item in selected_items:
            values = list(self.tree.item(item, 'values'))
            if len(values) > 8:
                # 更新监控状态
                values[8] = "未监控"
                self.tree.item(item, values=values)

                # 更新数据
                item_index = int(item)
                if item_index < len(self.match_data):
                    self.match_data[item_index].是否热门 = False
                    match_id = self.match_data[item_index].比赛ID
                    self.odds_monitor.remove_monitored_match(match_id)

                # 记录日志
                match_name = values[3]  # 比赛球队
                self.add_log(f"已取消监控: {match_name}", "INFO")

        messagebox.showinfo("成功", "监控取消成功！")

    def open_source_page(self):
        """跳转到源码网页"""
        selected_items = self.tree.selection()
        if not selected_items:
            messagebox.showwarning("警告", "请先选择要查看的比赛")
            return

        for item in selected_items:
            item_index = int(item)
            if item_index < len(self.match_data):
                # 使用示例URL，实际应用中可能需要根据比赛ID生成URL
                match_id = self.match_data[item_index].比赛ID
                url = f"https://vip.titan007.com/OverDown_n.aspx?id={match_id}&l=0"

                # 在浏览器中打开URL
                webbrowser.open_new_tab(url)

    def add_batch_monitoring(self):
        """批量添加已勾选的比赛到监控列表"""
        if not self.selected_items:
            messagebox.showwarning("警告", "请先勾选要监控的比赛")
            return

        added_count = 0
        # selected_items 存储的是 item_id (str)
        for item_id in self.selected_items:
            idx = int(item_id)
            if idx < len(self.match_data):
                match = self.match_data[idx]
                if match.比赛ID not in self.odds_monitor.monitored_matches:
                    self.odds_monitor.add_monitored_match(match.比赛ID)

                    # 更新Treeview显示
                    if self.tree.exists(item_id):
                        values = list(self.tree.item(item_id, 'values'))
                        if len(values) > 8:
                            values[8] = "监控中"
                            self.tree.item(item_id, values=values)

                    # self.add_log(f"添加监控: {match.主队名_简体} vs {match.客队名_简体}", "INFO")
                    added_count += 1

        if added_count > 0:
            self.add_log(f"已成功添加 {added_count} 场比赛到监控列表！", "INFO")
            self.update_status()
        else:
            messagebox.showinfo("提示", "选中的比赛已在监控列表中。")

    def clear_all_monitoring(self):
        """清空所有监控比赛"""
        if not self.odds_monitor.monitored_matches:
            messagebox.showinfo("提示", "当前没有正在监控的比赛")
            return

        if messagebox.askyesno("确认", "确定要清空所有监控比赛吗？"):
            self.odds_monitor.monitored_matches.clear()
            self.add_log("已清空所有监控比赛", "INFO")

            # 刷新 Treeview 显示
            for item_id in self.tree.get_children():
                values = list(self.tree.item(item_id, 'values'))
                if len(values) > 8 and values[8] == "监控中":
                    values[8] = "未监控"
                    self.tree.item(item_id, values=values)

            # 更新内存数据状态
            for match in self.all_match_data:
                match.是否热门 = False

            self.update_status()

    def populate_data(self):
        for item in self.tree.get_children():
            self.tree.delete(item)

        for i, match in enumerate(self.match_data):
            # 添加监控状态显示：根据 odds_monitor 中实际监控的比赛ID来判断
            monitoring_status = "监控中" if match.比赛ID in self.odds_monitor.monitored_matches else "未监控"

            # 构造显示值
            values = [
                "□",  # 选择框
                match.比赛ID,  # id
                match.比赛时间,  # 时间
                match.联赛名_简体,  # 赛事
                Spider007Util.get_match_status_text(match.比赛状态),

                f"{match.主队名_简体} vs {match.客队名_简体}",  # 比赛球队
                f"{match.主队比分}-{match.客队比分}",  # 比分
                f"{match.主队半场比分}-{match.客队半场比分}",  # 半场比分
                monitoring_status  # 监控状态
            ]

            item = self.tree.insert("", tk.END, values=values, iid=str(i))
            #
            # # 根据比赛状态设置标签
            # if match.比赛状态 == -1:  # 已结束
            #     self.tree.set(item, "状态", "完场")
            # elif match.比赛状态 == 0:  # 未开始
            #     self.tree.set(item, "状态", "未开始")
            # elif match.比赛状态 > 0:  # 进行中
            #     self.tree.item(item, tags=("live",))

    def add_log(self, message, level="INFO"):
        """添加日志消息"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        log_entry = f"[{timestamp}] {level}: {message}"
        self.log_messages.append(log_entry)

        if not self.log_paused:
            self.update_log_display()

    def update_log_display(self):
        """更新日志显示"""
        if self.log_paused or self.log_text is None:
            return

        self.log_text.config(state=tk.NORMAL)
        self.log_text.delete(1.0, tk.END)

        level_filter = self.log_level_var.get()

        for message in self.log_messages:
            # 过滤日志级别
            if level_filter != "ALL" and not f"{level_filter}:" in message:
                continue

            # 插入日志消息
            self.log_text.insert(tk.END, message + "\n")

            # 应用颜色标签
            if "INFO:" in message:
                self.log_text.tag_add("INFO", "end-2l", "end-1l")
            elif "WARN:" in message:
                self.log_text.tag_add("WARN", "end-2l", "end-1l")
            elif "ERROR:" in message:
                self.log_text.tag_add("ERROR", "end-2l", "end-1l")
            elif "DEBUG:" in message:
                self.log_text.tag_add("DEBUG", "end-2l", "end-1l")

        # 自动滚动到底部
        if self.auto_scroll_var.get():
            self.log_text.see(tk.END)

        self.log_text.config(state=tk.DISABLED)

    def clear_logs(self):
        """清空日志"""
        self.log_messages = []
        self.update_log_display()

    def toggle_log_pause(self):
        """切换暂停/继续日志更新"""
        self.log_paused = not self.log_paused
        if not self.log_paused:
            self.update_log_display()
            self.add_log("日志更新已继续", "INFO")
        else:
            self.add_log("日志更新已暂停", "WARN")

    def filter_logs(self):
        """根据级别过滤日志"""
        self.update_log_display()

    def filter_matches(self, event=None):
        filter_text = self.filter_entry.get_content().strip().lower()
        status_filter = self.status_filter_var.get()

        if not filter_text and status_filter == "全部":
            self.match_data = self.all_match_data.copy()
            self.filter_info.config(text="", fg="#666")
        else:
            filtered_data = []
            for match in self.all_match_data:
                # 1. 状态筛选
                status_match = True
                if status_filter == "滚球中":
                    if not match.是否走地:
                        status_match = False
                elif status_filter == "未开赛":
                    if match.比赛状态 != 0:
                        status_match = False
                elif status_filter == "已完场":
                    if match.比赛状态 != -1:
                        status_match = False

                if not status_match:
                    continue

                # 2. 文本筛选
                if filter_text:
                    teams = f"{match.主队名_简体} vs {match.客队名_简体}".lower()
                    if filter_text not in teams:
                        continue

                filtered_data.append(match)

            self.match_data = filtered_data
            if filtered_data:
                self.filter_info.config(text=f"找到 {len(filtered_data)} 场相关比赛", fg="#2196F3")
            else:
                self.filter_info.config(text="未找到相关比赛", fg="#f44336")

        self.selected_items.clear()
        self.populate_data()
        self.update_status()

    def clear_filter(self):
        self.filter_entry.clear(show_placeholder=True)
        self.filter_matches()

    def on_click(self, event):
        # 隐藏右键菜单
        self.hide_context_menu(event)

        region = self.tree.identify("region", event.x, event.y)
        if region == "cell":
            column = self.tree.identify_column(event.x)
            item = self.tree.identify_row(event.y)

            if column == "#1":  # 选择列
                current_value = self.tree.set(item, "选择")
                if current_value == "□":
                    self.tree.set(item, "选择", "✓")
                    self.selected_items.add(item)
                    match_info = self.tree.set(item, '比赛球队')
                    self.add_log(f"选中比赛: {match_info}", "INFO")
                else:
                    self.tree.set(item, "选择", "□")
                    self.selected_items.discard(item)

                self.update_status()

    def select_all(self):
        for item in self.tree.get_children():
            self.tree.set(item, "选择", "✓")
            self.selected_items.add(item)
        self.add_log("已全选所有比赛", "INFO")
        self.update_status()

    def invert_selection(self):
        for item in self.tree.get_children():
            current_value = self.tree.set(item, "选择")
            if current_value == "□":
                self.tree.set(item, "选择", "✓")
                self.selected_items.add(item)
            else:
                self.tree.set(item, "选择", "□")
                self.selected_items.discard(item)
        self.add_log("已反选比赛", "INFO")
        self.update_status()

    def delete_selected(self, event=None):
        if not self.selected_items:
            messagebox.showwarning("警告", "请先选择要删除的项目")
            return

        if messagebox.askyesno("确认删除", f"确定要删除选中的 {len(self.selected_items)} 场比赛吗？"):
            # 从数据中删除
            items_to_delete = sorted([int(i) for i in self.selected_items], reverse=True)
            deleted_matches = []

            for i in items_to_delete:
                if i < len(self.match_data):
                    match_info = f"{self.match_data[i].主队名_简体} vs {self.match_data[i].客队名_简体}"
                    deleted_matches.append(match_info)
                    del self.match_data[i]
                    # 同时从全部数据中删除
                    for j, match in enumerate(self.all_match_data):
                        if match == self.match_data[i] if i < len(self.match_data) else False:
                            del self.all_match_data[j]
                            break

            # 清空选择集并刷新显示
            self.selected_items.clear()
            self.populate_data()
            self.update_status()

            # 记录删除操作到日志
            for match in deleted_matches:
                self.add_log(f"已删除比赛: {match}", "INFO")

            # messagebox.showinfo("成功", "删除完成！")

    def refresh_data(self):
        try:
            self.add_log("开始刷新数据...", "INFO")
            self.root.update()  # 强制更新UI显示日志

            new_data = self.load_match_data()
            if new_data:
                self.all_match_data = new_data
                self.match_data = self.all_match_data.copy()

                self.selected_items.clear()
                self.clear_filter()
                
                # 自动添加滚球比赛到监控
                added_count = 0
                for match in self.all_match_data:
                    # 判断是否为滚球（走地）比赛
                    is_rolling = False
                    if hasattr(match, '是否走地'):
                        is_rolling = match.是否走地
                    elif hasattr(match, '比赛状态'):
                        # 1:上半场, 2:中场, 3:下半场
                        is_rolling = match.比赛状态 in [1, 2, 3]

                    if is_rolling :
                        if match.比赛状态 not in [0, 1, 2, 3]:
                            # 比赛状态不对的跳过
                            continue
                        if self.odds_monitor.add_monitored_match(match.比赛ID):
                            added_count += 1
                    
                if added_count > 0:
                     self.add_log(f"自动添加 {added_count} 场滚球比赛到监控", "INFO")
                
                self.filter_matches() # 刷新Treeview显示监控状态
                
                self.add_log(f"数据刷新完成，共获取 {len(self.all_match_data)} 场比赛", "INFO")
            else:
                self.add_log("刷新数据完成，但未获取到任何比赛数据", "WARN")

        except Exception as e:
            error_msg = f"刷新数据失败: {str(e)}"
            self.add_log(error_msg, "ERROR")
            messagebox.showerror("网络错误", f"无法获取比赛数据，请检查网络连接。\n\n详细错误: {e}")

    def update_status(self):
        total = len(self.match_data)
        selected = len(self.selected_items)
        total_all = len(self.all_match_data)

        if total == total_all:
            self.status_var.set(f"总共 {total} 场比赛，选中 {selected} 场")
        else:
            self.status_var.set(f"显示 {total}/{total_all} 场比赛，选中 {selected} 场")

    def show_monitor_dialog(self):
        """显示盘口监控对话框"""
        monitor_window = tk.Toplevel(self.root)
        monitor_window.title("盘口差异监控设置")
        monitor_window.geometry("700x650")
        monitor_window.resizable(True, True)

        # 使窗口居中显示
        monitor_window.update_idletasks()
        x = (monitor_window.winfo_screenwidth() // 2) - (700 // 2)
        y = (monitor_window.winfo_screenheight() // 2) - (650 // 2)
        monitor_window.geometry(f"700x650+{x}+{y}")

        # 监控控制面板
        control_frame = tk.LabelFrame(monitor_window, text="监控控制", font=("Arial", 10, "bold"))
        control_frame.pack(fill=tk.X, padx=10, pady=10)

        # 启动/停止监控按钮
        btn_frame = tk.Frame(control_frame)
        btn_frame.pack(fill=tk.X, padx=10, pady=5)

        start_btn = tk.Button(btn_frame, text="启动监控",
                              command=self.odds_monitor.start_monitoring,
                              bg="#4CAF50", fg="white")
        start_btn.pack(side=tk.LEFT, padx=5)

        stop_btn = tk.Button(btn_frame, text="停止监控",
                             command=self.odds_monitor.stop_monitoring,
                             bg="#f44336", fg="white")
        stop_btn.pack(side=tk.LEFT, padx=5)

        # # 手动检查按钮
        # check_btn = tk.Button(btn_frame, text="手动检查盘口",
        #                       command=self.manual_check_odds)
        # check_btn.pack(side=tk.LEFT, padx=5)

        # 阈值设置
        threshold_frame = tk.Frame(control_frame)
        threshold_frame.pack(fill=tk.X, padx=10, pady=5)

        tk.Label(threshold_frame, text="盘口差异阈值:").pack(side=tk.LEFT)
        threshold_var = tk.DoubleVar(value=self.odds_monitor.odds_threshold)
        threshold_entry = tk.Entry(threshold_frame, textvariable=threshold_var, width=8)
        threshold_entry.pack(side=tk.LEFT, padx=5)

        # ==========================================
        # 监控策略配置 (新增)
        # ==========================================
        strategy_frame = tk.LabelFrame(control_frame, text="监控策略", font=("Arial", 10, "bold"))
        strategy_frame.pack(fill=tk.X, padx=10, pady=5)

        monitor_handicap_var = tk.BooleanVar(value=self.odds_monitor.monitor_handicap_diff)
        tk.Checkbutton(strategy_frame, text="监控让球差异", variable=monitor_handicap_var).pack(side=tk.LEFT, padx=5)

        monitor_goals_var = tk.BooleanVar(value=self.odds_monitor.monitor_total_goals_diff)
        tk.Checkbutton(strategy_frame, text="监控总进球差异", variable=monitor_goals_var).pack(side=tk.LEFT, padx=5)

        auto_live_var = tk.BooleanVar(value=self.odds_monitor.auto_add_live)
        tk.Checkbutton(strategy_frame, text="自动添加走地比赛", variable=auto_live_var).pack(side=tk.LEFT, padx=5)

        # ==========================================
        # 走地异常监控配置
        # ==========================================
        anomaly_frame = tk.LabelFrame(control_frame, text="走地异常监控配置", font=("Arial", 10, "bold"), fg="blue")
        anomaly_frame.pack(fill=tk.X, padx=10, pady=10)

        # 开启开关
        anomaly_enabled_var = tk.BooleanVar(value=self.odds_monitor.enable_anomaly_monitor)
        anomaly_cb = tk.Checkbutton(anomaly_frame, text="开启走地异常监控", variable=anomaly_enabled_var)
        anomaly_cb.pack(anchor=tk.W, padx=5)

        # 参数输入区
        param_frame = tk.Frame(anomaly_frame)
        param_frame.pack(fill=tk.X, padx=5, pady=5)

        tk.Label(param_frame, text="初盘最小值(>=):").pack(side=tk.LEFT)
        min_init_var = tk.DoubleVar(value=self.odds_monitor.anomaly_min_initial)
        tk.Entry(param_frame, textvariable=min_init_var, width=5).pack(side=tk.LEFT, padx=2)

        tk.Label(param_frame, text="即时最大值(<=):").pack(side=tk.LEFT, padx=(10, 0))
        max_curr_var = tk.DoubleVar(value=self.odds_monitor.anomaly_max_current)
        tk.Entry(param_frame, textvariable=max_curr_var, width=5).pack(side=tk.LEFT, padx=2)

        tk.Label(param_frame, text="监控时间(分):").pack(side=tk.LEFT, padx=(10, 0))
        t_start_var = tk.IntVar(value=self.odds_monitor.anomaly_time_start)
        tk.Entry(param_frame, textvariable=t_start_var, width=4).pack(side=tk.LEFT)
        tk.Label(param_frame, text="-").pack(side=tk.LEFT)
        t_end_var = tk.IntVar(value=self.odds_monitor.anomaly_time_end)
        tk.Entry(param_frame, textvariable=t_end_var, width=4).pack(side=tk.LEFT)

        # ==========================================

        # 公司选择 - 修改为横向排列
        company_frame = tk.LabelFrame(control_frame, text="监控公司")
        company_frame.pack(fill=tk.X, padx=10, pady=5)

        # 创建一个框架来容纳公司选择标签和复选框
        company_selection_frame = tk.Frame(company_frame)
        company_selection_frame.pack(fill=tk.X, padx=5, pady=5)

        # 添加公司选择标签
        tk.Label(company_selection_frame, text="", font=("Arial", 9)).pack(side=tk.LEFT, padx=(0, 10))

        # 创建复选框框架，使用水平排列
        checkbox_frame = tk.Frame(company_selection_frame)
        checkbox_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)

        company_vars = {}
        for i, company in enumerate(self.odds_monitor.companies):
            var = tk.BooleanVar(value=company in self.odds_monitor.monitoring_companies)
            company_vars[company] = var

            # 创建复选框并水平排列 (移除实时更新事件)
            cb = tk.Checkbutton(checkbox_frame, text=company, variable=var)
            cb.pack(side=tk.LEFT, padx=8)

            # 每3个公司后添加一个分隔符（可选）
            if (i + 1) % 3 == 0 and i < len(self.odds_monitor.companies) - 1:
                sep = ttk.Separator(checkbox_frame, orient=tk.VERTICAL)
                sep.pack(side=tk.LEFT, padx=5, fill=tk.Y, pady=5)

        # ==========================================
        # 通知设置
        # ==========================================
        notification_btn_frame = tk.Frame(control_frame)
        notification_btn_frame.pack(fill=tk.X, padx=10, pady=10)

        def open_notification_config():
            config_window = tk.Toplevel(monitor_window)
            config_window.title("通知配置")
            config_window.geometry("600x700")

            # 居中
            config_window.update_idletasks()
            x = (config_window.winfo_screenwidth() // 2) - (600 // 2)
            y = (config_window.winfo_screenheight() // 2) - (700 // 2)
            config_window.geometry(f"600x700+{x}+{y}")

            config_frame = NotificationConfigFrame(config_window, config_file_path=get_full_config_path())
            config_frame.pack(fill=tk.BOTH, expand=True)

        tk.Button(notification_btn_frame, text="打开通知配置", command=open_notification_config,
                  bg="#9C27B0", fg="white", font=("Arial", 10)).pack(fill=tk.X)
        # ==========================================

        # 保存配置按钮区域
        save_frame = tk.Frame(control_frame)
        save_frame.pack(fill=tk.X, padx=10, pady=10)

        def save_all_settings():
            try:
                # 1. 保存盘口阈值
                threshold = threshold_var.get()
                self.odds_monitor.set_odds_threshold(threshold)

                # 2. 保存异常监控配置
                self.odds_monitor.set_anomaly_config(
                    anomaly_enabled_var.get(),
                    min_init_var.get(),
                    max_curr_var.get(),
                    t_start_var.get(),
                    t_end_var.get()
                )

                # 3. 保存监控策略
                self.odds_monitor.set_monitor_config(
                    monitor_handicap_var.get(),
                    monitor_goals_var.get(),
                    auto_live_var.get()
                )

                # 4. 保存监控公司
                selected_companies = []
                for comp, var in company_vars.items():
                    if var.get():
                        selected_companies.append(comp)
                self.odds_monitor.set_monitoring_companies(selected_companies)

                # 5. 统一保存到文件 (不包含通知配置，通知配置独立管理)
                self.odds_monitor.save_config()

                # 重新加载配置以同步可能的通知更改
                self.odds_monitor.load_config()

                messagebox.showinfo("保存成功", "监控配置已更新并保存。\n(注意：通知配置请在'打开通知配置'中单独保存)")

            except ValueError:
                messagebox.showerror("错误", "请输入有效的数字参数")
            except Exception as e:
                messagebox.showerror("错误", f"保存配置失败: {str(e)}")

        tk.Button(save_frame, text="保存所有配置", command=save_all_settings,
                  bg="#2196F3", fg="white", font=("Arial", 10, "bold"), width=20).pack()

        # 监控状态显示
        status_frame = tk.LabelFrame(monitor_window, text="监控状态", font=("Arial", 10, "bold"))
        status_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        status_text = tk.Text(status_frame, height=10, wrap=tk.WORD)
        scrollbar = tk.Scrollbar(status_frame, command=status_text.yview)
        status_text.config(yscrollcommand=scrollbar.set)

        status_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 更新状态显示
        def update_status():
            status = self.odds_monitor.get_monitoring_status()

            status_text.delete(1.0, tk.END)

            # 异常监控状态文本
            anomaly_status = "开启" if self.odds_monitor.enable_anomaly_monitor else "关闭"
            if self.odds_monitor.enable_anomaly_monitor:
                anomaly_desc = f"(初>={self.odds_monitor.anomaly_min_initial}, 即<={self.odds_monitor.anomaly_max_current})"
            else:
                anomaly_desc = ""

            status_info = f"""监控状态: {'运行中' if status['is_monitoring'] else '已停止'}
    异常监控: {anomaly_status} {anomaly_desc}
    监控比赛: {status['monitored_matches']} 场
    监控公司: {status['monitoring_companies']} 家
    差异阈值: {status['threshold']}

    监控中的比赛:
    """

            status_text.insert(tk.END, status_info)

            for match_id in self.odds_monitor.monitored_matches:
                min_odds, max_odds, odds_range = self.odds_monitor.calculate_odds_range(match_id)
                match_info = self.odds_monitor.get_match_info(match_id)

                status_line = f"- {match_info}: {odds_range:.3f} ({min_odds:.3f} ~ {max_odds:.3f})\n"
                status_text.insert(tk.END, status_line)

                # 高亮显示超过阈值的项目
                if odds_range > self.odds_monitor.odds_threshold:
                    status_text.tag_add("alert", "end-2l", "end-1l")

            status_text.tag_configure("alert", foreground="red")

            # 5秒后再次更新
            monitor_window.after(5000, update_status)

        update_status()

    def update_companies(self, company, var):
        """更新监控的公司"""
        if var.get():
            self.odds_monitor.monitoring_companies.add(company)
        else:
            self.odds_monitor.monitoring_companies.discard(company)

        company_list = ", ".join(self.odds_monitor.monitoring_companies)
        self.add_log(f"监控公司更新为: {company_list}", "INFO")

    def manual_check_odds(self):
        """手动检查盘口差异"""
        alerts = self.odds_monitor.check_odds_alerts()
        if alerts:
            for alert in alerts:
                self.add_log(f"手动检查: {alert}", "WARN")
            messagebox.showwarning("盘口差异告警", f"发现 {len(alerts)} 个告警")
        else:
            self.add_log("手动检查: 未发现盘口差异", "INFO")

    def update_monitor_status(self):
        """更新监控状态显示（在状态栏）"""
        status = self.odds_monitor.get_monitoring_status()
        monitor_text = f" | 监控: {'运行中' if status['is_monitoring'] else '已停止'}({status['monitored_matches']}场)"

        current_text = self.status_var.get()
        if "| 监控:" in current_text:
            # 替换现有的监控状态
            base_text = current_text.split("| 监控:")[0].strip()
            self.status_var.set(base_text + monitor_text)
        else:
            # 添加监控状态
            self.status_var.set(current_text + monitor_text)

        # 5秒后再次更新
        self.root.after(5000, self.update_monitor_status)

    def show_alert_dialog(self, title, message, match_id=None):
        """在Treeview中高亮显示告警比赛"""
        if match_id:
            # 查找对应的Treeview项
            for item_id in self.tree.get_children():
                values = self.tree.item(item_id, 'values')
                if values and str(values[1]) == str(match_id):  # 假设比赛ID在第二列
                    self.tree.item(item_id, tags=("alert_highlight",))
                    self.add_log(f"比赛 {values[5]} 已标记为告警状态 (ID: {match_id})", "WARN")
                    break
        else:
            # 如果没有match_id，则 fallback 到日志或通用警告
            self.add_log(f"通用告警: {title} - {message}", "WARN")

    def __del__(self):
        """析构函数，停止日志线程"""
        self.log_running = False
        if hasattr(self, 'odds_monitor'):
            self.odds_monitor.stop_monitoring()

    def load_match_data(self) -> List[MatchDataV2]:
        parser = FootballMatchParser()
        # with open('../core/spider/html/bfdata.js', 'r', encoding='utf-8') as f:
        #     today_match_bf_content_js = f.read()

        apiZeroSeven = ApiZeroSeven()
        today_match_bf_content_js = apiZeroSeven.get_today_match_bf_data()
        result = parser.process_js_content(today_match_bf_content_js)

        # 调用转换方法将解析后的数据转换为MatchDataV2对象
        match_data_v2_list = parser.convert_matches_to_match_data_v2(result['matches'])
        print(f"成功转换 {len(match_data_v2_list)} 条比赛数据为MatchDataV2对象")
        #
        # for match_data in match_data_v2_list:
        #     print(match_data)

        return match_data_v2_list


def main():
    root = tk.Tk()
    app = MatchViewer(root)

    # 设置窗口关闭事件
    def on_closing():
        app.log_running = False
        if hasattr(app, 'odds_monitor'):
            app.odds_monitor.stop_monitoring()
        root.destroy()

    root.protocol("WM_DELETE_WINDOW", on_closing)
    root.mainloop()


if __name__ == "__main__":
    main()
